/*
 * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package com.dc.gameserver.serverCore.controller.handleController.pveCoreController;

import com.dc.gameserver.baseConfig.Config;
import com.dc.gameserver.exceptions.logicException;
import com.dc.gameserver.hardCode.CardType;
import com.dc.gameserver.hardCode.playerGameStatus;
import com.dc.gameserver.proto.gameserverprotoVo.*;
import com.dc.gameserver.serverCore.controller.AbstractController.AbstractController;
import com.dc.gameserver.serverCore.controller.AbstractController.IController;
import com.dc.gameserver.serverCore.model.gamemodel.script.ScriptFactory;
import com.dc.gameserver.serverCore.service.battle.GameFormula;
import com.dc.gameserver.serverCore.service.cardModule.Card;
import com.dc.gameserver.serverCore.service.cardModule.CardBox;
import com.dc.gameserver.serverCore.service.cardModule.CardBoxManager;
import com.dc.gameserver.serverCore.service.character.GameCharacter;
import com.dc.gameserver.serverCore.service.character.Monster;
import com.dc.gameserver.serverCore.service.character.PlayerInstance;
import com.dc.gameserver.serverCore.service.managerService.ThreadPoolManager;
import com.google.protobuf.MessageLite;
import javolution.util.FastTable;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 石头哥哥
 *         Date: 13-12-5</br>
 *         Time: 下午12:03</br>
 *         Package: com.dc.gameserver.serverCore.controller.handleController.pveCoreController</br>
 *         注解：PVE战斗中 当玩家触发当前控制器，就会判定logic计算；
 *         玩家触发该控制器，那么战斗就将会开始，monster的牌自动处理，
 *         触发该处理器 player一定不处于眩晕状态；
 *         如果player处于眩晕状态，那么就直接逻辑处理monster出牌，然后逻辑计算！
 */
@Service
@SuppressWarnings("unchecked")
public class pveHandleOutCardController extends AbstractController {

    @Override
    public void PostConstruct() {
        int ID= pveOutCardRequest.msgID.ID_VALUE;
        GAME_CONTROLLERS[ID]=this;   //业务逻辑处理引用
        IController.MESSAGE_LITE[ID]= pveOutCardRequest.getDefaultInstance();   //解析的pb实体类型
    }

    /**
     * messageLite数据结构体分发
     *
     * @param messageLite 数据载体
     * @param player      active object
     * @throws Exception 注意messageLite应该递交给GC直接处理  ，set null
     *
     */
    @Override
    public void DispatchMessageLit(MessageLite messageLite, PlayerInstance player) throws Exception {
        /**
         * 法力值，出牌类型，最大出牌数量规则等，前端根据规则以及后端推送更新的数据进行过滤
         */
        final CardBox cardBox= CardBoxManager.getCardBoxByID(player.getCardBoxID());
        /**
         * 移除回合中出牌计时任务
         * 玩家在规定时间内主动出牌，将会移除注册的回合出牌超时计时任务
         */
        CardBoxManager.removeRoundTimeOutTask(cardBox.getCardBoxID());

        int result=0;
        /**临时出牌列表（判定玩家是否都出牌到预出牌临时区域）*/
        FastTable<GameCharacter> checkList=cardBox.getCheckOutCardPlayerList();// if PVE  only one player
        //1.出牌类型异常，2.放弃出牌操作成功，3.出牌操作成功；4.出牌张数，5.出牌是非法牌；6.出技能牌失败，法力值不够  ;7.防御失败，法力值不足
        if (cardBox!=null){
            pveOutCardRequest outCardRequest= (pveOutCardRequest) messageLite;
            int skillID=outCardRequest.getSkillID();  //玩家使用技能编号
            if(skillID!=0){
                //使用技能 ，那么该技能应该是装备
                player.setReduceMagic(ScriptFactory.skillModelFastMap.get(skillID).getReduceMagic());
                chooseSkillResponse.Builder builder=chooseSkillResponse.newBuilder();

                boolean haveSkill= player.checkSkill(skillID);
                if (haveSkill){ //技能已经装备有效
                    player.setBattleSkillID(skillID);
                    if (player.invokeFiveTypeSkillValue(skillID)){
                        builder.setResult(0x1);
                        player.DirectSend(wrappedBufferShort(chooseSkillResponse.msgID.ID_VALUE,builder.build()));
                    }
                }else {
                    builder.setResult(0x2);
                    player.DirectSend(wrappedBufferShort(chooseSkillResponse.msgID.ID_VALUE,builder.build()));
                    return;
                }
            }

            List<netCardVO> netCardVOList=outCardRequest.getNetCardVOList();
            boolean giveOut=outCardRequest.getGiveOut();
            if (!giveOut){
                int  cardType= netCardVOList.get(0).getCardNum();
                if (netCardVOList.size()>=1){
                    for (netCardVO netCardVO:netCardVOList){
                        if (netCardVO.getCardNum()!=cardType){
                            result=1;
                            outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                            builder.setResult(result);
                            player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                            return;
                        }
                    }
                }
                /**
                 * 检查出牌技能，防御等 法力值是否足够
                 */
                int cardNum= netCardVOList.size();
                //magic check
                if (cardType== CardType.MAGIC_TYPE.getType()){
                    int magic= GameFormula.computeMagicUse(player);
                    if (player.getCurrentMagic()<magic){
                        outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                        result=6;
                        builder.setResult(result);    //6.出技能牌失败，法力值不够
                        player.DirectSend(CardBox.wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                        return ;
                    }
                }

                //defence check
                if (cardType==CardType.DEFENCE_TYPE.getType()){
                    int magic= GameFormula.ComputeDeffenceLoss(player,cardNum);
                    if (player.getCurrentMagic()<magic){
                        outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                        result=7;
                        builder.setResult(result);    //7.出防御牌失败，法力值不够
                        player.DirectSend(CardBox.wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                        return;
                    }
                }
                /**
                 * 牌的张数验证
                 */
                if (netCardVOList.size()> player.getMaxOutCard()){
                    result=4;
                    outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                    builder.setResult(result);
                    player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
                    return;
                }
                /**
                 * 验证出牌的合法性
                 */
                if (!player.checkCard(netCardVOList)){
                    //出牌不合法
                    result=5;
                    outCardResponseResult.Builder builder=outCardResponseResult.newBuilder();
                    builder.setResult(result);
                    player.DirectSend(wrappedBufferShort(outCardResponseResult.msgID.ID_VALUE,builder.build()));
//                   player.getChannel().close();   // close channel
                    return;
                }
            }

            /****player 出牌合法,正常逻辑处理***/
            /**
             * 检查眩晕     system active
             */
            for (GameCharacter pp:checkList){
                int DizzinessTimes= pp.getDizzinessTimes();
                if (DizzinessTimes>0){   //眩晕状态，被通知不出牌
                    if (pp instanceof PlayerInstance){
                        throw new logicException("pp 一定是Monster :"+pp.getName());
                    }
                    DizzinessTimes=DizzinessTimes-1;
                    pp.setDizzinessTimes(DizzinessTimes);
                    if (pp.getDizzinessTimes()<=0){
                        //notify player ,the monster will be in dis dizziness
                        pp.setDizzinessTimes(0);
                        dizzniessResponse.Builder builder=dizzniessResponse.newBuilder();
                        builder.setPlayerID(pp.getID());
                        builder.setResult(playerGameStatus.undizziness.getStatus());
                        cardBox.submitMessageToEveryOne(wrappedBufferShort(dizzniessResponse.msgID.ID_VALUE, builder.build()));
                    }

                    /**
                     * 当前逻辑是player触发，那么player一定不会眩晕状态
                     * 所以处于眩晕，那么该对象一定是monster
                     */
                    checkList.remove(pp);
                }
            }
            //monster 眩晕了 ，将会被移除，那么将不会出牌，而针对monster不会被注册出牌计时器
            //ready for monster card,if the monster is still in checkList  （not in dizziness status）
            FastTable<GameCharacter>tempOutcardList=cardBox.getTempOutCardPlayerList();
            Monster monster= (Monster) checkMonsterInList(checkList);
            if (monster!=null){
                /**获取monster 出牌*/
                FastTable<Card> monsterCard=monster.monsterOutCards();
                if (monsterCard!=null){
                    for (Card c:monsterCard){
                        monster.addOutCard(c);
                    }
                    monsterCard.clear();
                    monsterCard=null;  //清除引用
                    tempOutcardList.addAll(monster);
                    checkList.remove(monster);
                }else {
                    //monster 法力值不够 玩家放弃出牌 返回
                    checkList.remove(monster);
                    if (giveOut){
                        //all give out
                        cardBox.flushBloodAndMagic();
                        cardBox.resetRoundResource();
                        return;
                    }
                }
            }

           if (monster==null&&giveOut){
               //玩家放弃出牌  monster眩晕
               //all give out
               cardBox.flushBloodAndMagic();
               cardBox.resetRoundResource();
               return;
           }

            //player give out card , the monster never give out card,otherwise there's no suite card to out
            if(giveOut){
                checkList.remove(player);  //remove  player if give out card!
                int size= checkList.size();
                if (size==0&&monster.getOutCardsList().size()!=0){
                    CardBoxManager.coreLogic(cardBox);
                    return;
                }
                //monster 眩晕，player放弃出牌,通知出牌
                if (size==0){
                    cardBox.flushBloodAndMagic();
                    cardBox.resetRoundResource();
                    return;
                }
            }

            //player out card
            if (!giveOut&&!netCardVOList.isEmpty()) {
                for (netCardVO netCardVO:netCardVOList){
                    /**清理玩家当前的牌库*/
                    Card card= player.removeIncardlib(netCardVO.getCardNum(), netCardVO.getCardCount());
                    if (card==null){
                       throw  new logicException("card must be not empty ,check out... ...");
                    }
                    /**添加到临时出牌库*/
                    if (card!=null)player.addOutCard(card);
                }
                /**添加玩家到出牌列表中 ready for logic dispatcher***/
                tempOutcardList.addLast(player);
                /**set card type 出牌类型 便于后期逻辑处理计算 额 出牌类型应该必须一致（前端验证）**/
                int cardNum=netCardVOList.get(0).getCardNum();
                /**设置牌类型 牌类型做准备***/
                player.setCardType(CardType.getTypeByFlg(cardNum));
                checkList.remove(player);
                result=3 ;
            }
            pveOutCardResponse.Builder builder=pveOutCardResponse.newBuilder();
            builder.setResult(result);
            player.DirectSend(wrappedBufferShort(pveOutCardResponse.msgID.ID_VALUE,builder.build()));
            outCardRequest =null;        // by GC collection

            /***
             * 检查出牌是否完毕
             */
            if (checkList.size()==0){
                if (Config.DEFAULT_VALUE.SERVER_VALUE.useMultleThread){
                    final Runnable task=new Runnable() {
                        @Override
                        public void run() {
                            CardBoxManager.coreLogic(cardBox);
                        }
                    } ;
                    ThreadPoolManager.getInstance().executeCalculate(task);
                } else {
                    CardBoxManager.coreLogic(cardBox);
                }
            }
        }else {
            throw  new logicException("逻辑异常，请仔细检查！cardBoxManager must not be null");
        }

    }



    /**
     * 检查monster是否还咋checkList ,如果monster处于眩晕状态 就会被移除
     * @param checkList
     * @return
     */
    private GameCharacter checkMonsterInList(FastTable<GameCharacter> checkList){
        GameCharacter monster=null;
        for (GameCharacter p:checkList){
            if (p instanceof Monster){
                monster=p;
                break;
            }
        }
        return monster;
    }
}
